<template>
  <div class="cps-search-form">
    <!-- a-row 用于布局，设置列间距为 24 -->
    <a-row :gutter="24">
      <!-- 循环渲染 a-col，根据 showSearchDataList 的数据 -->
      <a-col
        :span="colSpan"
        v-for="(item, index) in showSearchDataList"
        :key="index"
      >
        <!-- 每个筛选项：
               -标签label（slot1） + 输入控件（slot2）
        -->
        <div class="flex mb-6px items-center">
          <!-- 具名插槽，根据 item.requestStr 拼接的字符串命名 -->
          <slot :name="`${item.requestStr}TR`" :record="item">
            <!-- 标签，显示 item.columnName 的值 -->
            <label class="w-120px tar mr-6px"> {{ item.columnName }}: </label>
          </slot>
          <slot :name="`${item.requestStr}CR`" :record="item">
            <!-- 
              原生a-select
              根据不同条件渲染不同的输入组件 
                  -mode: item.model为0多选，1为单选
                  -maxTagCount: 最多显示多少个 tag
                  -placeholder: 搜索+item.columnName
                  -v-model：收集到formdata[请求回来的searchStr字段]
                  -:filter-option: 模糊搜索
                  -@focus: 调用getConfigColumn获取options数据
            -->
            <a-select
              class="w-full"
              v-if="item.model === 0 || item.model === 6"
              :mode="item.model === 6 ? undefined : 'multiple'"
              :placeholder="'搜索' + item.columnName"
              :maxTagCount="2"
              v-model:value="formdata[item.searchStr]"
              :filter-option="filterOption"
              option-label-prop="label"
              show-search
              allow-clear
              @focus="
                () => {
                  getConfigColumn(item)
                }
              "
            >
              <!-- 循环渲染 a-select-option，根据 item.options 的数据 -->
              <a-select-option
                v-for="val in item.options"
                :value="val.value"
                :label="val.label"
                :key="val.value"
                >{{ val.label }}</a-select-option
              >
            </a-select>
            <!-- 
              远程拉取下拉框remote-select
              根据不同条件渲染不同的输入组件 
                  -mode: item.model为0多选，1为单选
                  -maxTagCount: 最多显示多少个 tag
                  -placeholder: 搜索+item.columnName
                  -v-model：收集到formdata[请求回来的searchStr字段]
            -->
            <remote-select
              v-if="item.model === 2"
              :placeholder="'搜索' + item.columnName"
              class="w-full"
              :maxTagCount="1"
              v-model:value="formdata[item.searchStr]"
              :menuName="item.menuName"
              mode="multiple"
              :token-separators="[' ', ',']"
              :columnName="item.searchStr"
            />
            <!-- 注释建议给个 url -->
            <cps-cascader
              v-if="item.model === 4"
              v-model:value="formdata[item.searchStr]"
              class="w-full"
              change-on-select
              :placeholder="'搜索' + item.columnName"
              v-bind="componentConfig"
            ></cps-cascader>
            <a-range-picker
              dropdownClassName="date-range"
              v-if="item.model === 1"
              class="w-full"
              format="YYYY-MM-DD"
              valueFormat="YYYY-MM-DD"
              v-model:value="formdata[item.searchStr]"
              :placeholder="['开始日期', '结束日期']"
            />
            <a-radio-group
              size="small"
              class="w-full"
              v-if="item.model === 5"
              v-model:value="formdata[item.searchStr]"
            >
              <!-- 循环渲染 a-radio，根据 item.options 的数据 -->
              <a-radio
                v-for="(val, inde) in item.options"
                :key="inde"
                :value="val.value"
                >{{ val.label }}</a-radio
              >
            </a-radio-group>
            <a-textarea
              class="w-full"
              v-if="item.model === 3"
              v-model:value="formdata[item.searchStr]"
              :placeholder="'搜索' + item.columnName"
              :row="3"
            ></a-textarea>
            <a-input
              class="w-full"
              v-if="item.model === 8"
              v-model:value="formdata[item.searchStr]"
              :placeholder="'搜索' + item.columnName"
            ></a-input>
            <a-input-number
              v-if="item.model === 9"
              class="w-full"
              v-model:value="formdata[item.searchStr]"
              :placeholder="'搜索' + item.columnName"
              :min="0"
            >
            </a-input-number>
          </slot>
        </div>
      </a-col>
      <!-- 根据条件渲染 a-col，用于显示操作按钮 -->
      <a-col :span="actionSpan" v-if="showSearchDataList.length">
        <a-space style="float: right">
          <!-- cps-button，用于切换筛选状态，数据大于4条时显示 -->
          <cps-button
            :throttle="0"
            size="small"
            type="link"
            @click="toggleMoreFilter"
            v-if="searchDataList.length > DISPLAY_MAX_ON_FOLDED"
          >
            <!-- 根据折叠状态显示不同的模板 -->
            <template v-if="state.isFolder">
              <DownOutlined />更多筛选
            </template>
            <template v-else> <UpOutlined />收起筛选 </template>
          </cps-button>
          <!-- cps-button，用于触发重置操作 -->
          <cps-button size="small" @click="onReset">重置</cps-button>
          <!-- cps-button，用于触发搜索操作 -->
          <cps-button size="small" type="primary" @click="onSearch"
            >搜索</cps-button
          >
        </a-space>
      </a-col>
    </a-row>
  </div>
</template>

<!--
  cps-filter组件使用条件：
    1. data返回字段要求： 
      -isSelected：是否为select下拉框
      -columnName：筛选框描述标签||为下拉框入参（数据为下拉框类型时）
      -model：筛选框类型
          || 0: 多选select || 2: remote-select || 3: a-textarea  || 4: cps-cascader || 5: a-radio-group
          || 6: 单选select || 8: input         || 9: input-number
      -searchStr：搜索时表单收集的formdata绑定的键key
      -menuName
      -fieldDescVo: model为5时（a-radio-group）
    2. 接口要求： 
      - @/apis/1890.js
      - 筛选框：
          url: config.list_menu_field_post（/config/list-menu-field）
          insertData:{
              menuName: item.menuName(props)
          }
      - 数据：下拉框
          url: /config/list-menu-field（config.list_column_post）
          insertData:{
              menuName: item.menuName,
              columnName: item.searchStr
          }
 -->
<script setup>
import { config } from '@/apis/1890.js'
import { DownOutlined, UpOutlined } from '@ant-design/icons-vue'
import { computed, onMounted, reactive, toRefs } from 'vue'
import { cloneDeep } from 'lodash-es'

/* 
  props说明:
    - menuName: 请求筛选列数据的入参
    - componentConfig: 这个配置项仅限于cps-cascader(级联选择器组件),v-bind绑定在cps-cascader上
*/
const props = defineProps({
  menuName: {
    type: String,
    default: ''
  },
  componentConfig: {
    type: Object,
    default: () => {}
  }
})

// 定义组件发出的事件
const emits = defineEmits(['reset', 'search'])

// 定义收起时展示的个数
const DISPLAY_MAX_ON_FOLDED = 4

// 创建响应式数据对象
const state = reactive({
  dataList: [], // 筛选框数据源，data一层处理，getConfigColumn二层处理增加options
  formdata: {}, // 存储表单数据
  col: 3, // 列数
  isFolder: true, // 是否折叠状态
  showMax: DISPLAY_MAX_ON_FOLDED // 显示的最大数量
})

// 计算属性，根据 state.dataList 过滤出 isSelected 为 1 的项
const searchDataList = computed(() => {
  return state.dataList?.filter(item => item.isSelected === 1) || []
})

// 计算属性，根据折叠状态和显示最大数量从 searchDataList 中截取一部分数据进行显示
const showSearchDataList = computed(() => {
  return searchDataList.value?.slice(0, state.showMax)
})

// 计算属性，计算列跨度，默认为8
const colSpan = computed(() => {
  return 24 / state.col
})

// 计算属性，计算操作按钮所在列的跨度
const actionSpan = computed(() => {
  const r = showSearchDataList.value.length % 3
  return 24 - colSpan.value * r
})

// 切换折叠状态的方法
const toggleMoreFilter = () => {
  state.isFolder = !state.isFolder
  if (!state.isFolder) {
    state.showMax = searchDataList.value.length
  } else {
    state.showMax = DISPLAY_MAX_ON_FOLDED
  }
}

// 用于在输入框进行模糊搜索时对选项进行过滤
const filterOption = (inputValue, option) => {
  console.log(inputValue, option)
  return option.label.toLowerCase().indexOf(inputValue.toLowerCase()) >= 0
}

/* 
  focus:获取下拉框options:
     -对showSearchDataList数据二次处理添加item.options：
     -select收集接口返回数据的key字段
     -去掉key为空的options 
  注意： 对传入的参数item进行操作并修改了item.options，会影响到原始的item对象； 因为对象在 JavaScript 中是按引用传递的
*/
const getConfigColumn = async item => {
  console.log(item)
  const { success, data } = await config.list_column_post({
    menuName: item.menuName,
    columnName: item.searchStr
  })
  if (success) {
    item.options = (data || [])
      .filter(_ => {
        return _.key != null && _.key !== ''
      })
      .map(_ => {
        return {
          label: _.value,
          value: _.key
        }
      })
  } else {
    console.log(data)
  }
}

// 获取筛选框数据
const getMenuField = async () => {
  const { data } = await config.list_menu_field_post({
    menuName: props.menuName
  })
  data?.map(item => {
    // 下拉框
    if (item.isSelected) {
      state.formdata[item.searchStr] = undefined
    }
    // a-radio-group
    if (item.model === 5) {
      item.options = item.fieldDescVo
      const checkedValue = item.options.filter(item => item.checked)
      if (checkedValue.length) {
        if (item.isSelected) {
          state.formdata[item.searchStr] = checkedValue[0].value
        }
      }
    }
  })
  state.defaultFormdata = cloneDeep(state.formdata)
  state.dataList = data
}

// 触发搜索事件的方法
const onSearch = () => {
  setTimeout(() => {
    emits('search', state.formdata)
  }, 200)
}

// 触发重置事件的方法
const onReset = () => {
  state.formdata = cloneDeep(state.defaultFormdata)
  setTimeout(() => {
    emits('reset', state.defaultFormdata)
  }, 200)
}

// 组件挂载时调用的方法
onMounted(() => {
  props.menuName && getMenuField()
})

// 提取 state 中的 formdata 为响应式引用
const { formdata } = toRefs(state)
</script>
<style lang="scss" scoped>
.ant-radio-wrapper {
  font-size: 12px;
}
</style>
